﻿using SolidWorks.Interop.sldworks;
using SolidWorks.Interop.swconst;
using SolidWorks.Interop.swpublished;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;

namespace Demo
{
    public class PMPHandlerForOpenHole : PropertyManagerPage2Handler9
    {
        private ISldWorks swApp;
        private ModelDoc2 topAsemDoc;
        private UserPMPForOpenHole ppage;
        private bool NeedOpenHole;
        private List<Component2> compTarget;    // 开孔组件列表
        private List<Face2> faceTarget;         // 开孔面列表
        private List<Face2> faceBaseList;       // 孔基准面列表

        bool RotaionSlotHole;   // 腰孔是否旋转90°
        bool RemoveMappingRealtion = true; // 保持映射关系
        public PMPHandlerForOpenHole(ISldWorks _swApp, UserPMPForOpenHole userPMP)
        {
            swApp = _swApp;
            ppage = userPMP;
            topAsemDoc = swApp.IActiveDoc2;
        }

        public void AfterActivation()
        {
        }

        public void OnClose(int Reason)
        {
            if (Reason == 1)
            {
                try
                {
                    compTarget = new List<Component2>();
                    faceTarget = new List<Face2>();
                    faceBaseList = new List<Face2>();
                    SelectionMgr selMgr = swApp.IActiveDoc2.ISelectionManager;

                    // 获得开孔基准面
                    int faceBaseCount = ppage.selectionFaceBase.ItemCount;
                    if (faceBaseCount <= 0)
                    {
                        return;
                    }
                    int faceBaseMark = ppage.selectionFaceBase.Mark;

                    for (int i = 1; i <= faceBaseCount; i++)
                    {
                        Face2 faceBaseComp = (Face2)selMgr.GetSelectedObject6(i, faceBaseMark);
                        faceBaseList.Add(faceBaseComp);
                    }

                    // 获得开孔目标面
                    int faceTargetCount = ppage.seletionFaceTarget.ItemCount;
                    int faceTargetMark = ppage.seletionFaceTarget.Mark;
                    if (faceTargetCount <= 0)
                    {
                        return;
                    }

                    for (int i = 1; i <= faceTargetCount; i++)
                    {
                        Component2 compSelected = (Component2)selMgr.GetSelectedObjectsComponent4(i, faceTargetMark);
                        Face2 faceSelected = (Face2)selMgr.GetSelectedObject6(i, faceTargetMark);
                        if (faceSelected == null || compSelected == null)
                        {
                            continue;
                        }

                        faceTarget.Add(faceSelected);
                        compTarget.Add(compSelected);
                    }

                    NeedOpenHole = true;
                }
                catch (Exception e)
                {
                    NeedOpenHole = false;
                }
            }
            else
            {
                NeedOpenHole = false;
            }
        }

        public void AfterClose()
        {
            if (NeedOpenHole)
            {
                for (int i = 0; i < compTarget.Count; i++)
                {
                    try
                    {
                        CreateHole(faceBaseList, compTarget[i].IGetModelDoc(), faceTarget[i]);
                    }
                    catch (Exception e)
                    {
                        continue;
                    }
                }
            }
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="refernceFace">开孔参照面</param>
        /// <param name="compDoc">开孔面所在的零件</param>
        /// <param name="faceSketchOn">开孔面</param>
        private void CreateHole(List<Face2> refernceFaces, ModelDoc2 compDoc, Face2 faceSketchOn)
        {
            topAsemDoc = swApp.IActiveDoc2;
            PartDoc prtDoc = compDoc as PartDoc;
            SketchManager skMgr = topAsemDoc.SketchManager;
            FeatureManager featMgr = topAsemDoc.FeatureManager;

            #region 映射孔的实体引用

            topAsemDoc.ClearSelection();
            // 选择要开孔的面
            var selectRes = (faceSketchOn as Entity).Select(true);

            (topAsemDoc as AssemblyDoc).EditPart();// 编辑零件

            // 选择要开孔的面
            selectRes = (faceSketchOn as Entity).Select(true);

            skMgr.InsertSketch(true);

            selectRes = (faceSketchOn as Entity).DeSelect(); // 取消选择面

            // 选择基准面上面的孔
            foreach (Face2 face in refernceFaces)
            {
                selectAllHoldInFace(face);
            }

            bool convertEnityRes = skMgr.SketchUseEdge3(false, false);
            if (convertEnityRes == false)
            {
                swApp.SendMsgToUser("映射草图失败");
            }

            // 获得映射来的草图
            Sketch mappingSketch = skMgr.ActiveSketch;
            // 遍历当前草图，去掉 转换实体引用的几何关系

            object[] segments = (object[])mappingSketch.GetSketchSegments();

            object[] mappingSketchContours = (object[])mappingSketch.GetSketchContours();
            int numContours = mappingSketchContours.Length;

            for (int i = 0; i < numContours; i++)
            {
                // 草图轮廓
                SketchContour countour = (SketchContour)mappingSketchContours[i];

                //var edgesCount = countour.GetEdgesCount();  // 当前草图轮廓所包含的边线数量

                object[] countourSegments = (object[])countour.GetSketchSegments(); // 把当前的草图轮廓分解成草图段
                var edgesCount = countourSegments.Length;    // 草图轮廓包含的草图段数量

                // 如果旋转槽口
                if (RotaionSlotHole)
                {
                    // 删除约束关系
                    if (edgesCount == 1)  // 如果是圆孔
                    {
                        //countour.Select(true, -1);
                        SketchSegment skSeg = (SketchSegment)countourSegments[0];
                        skSeg.Select(false);

                        topAsemDoc.SketchConstraintsDel(0, "sgOFFSETEDGE");
                    }
                    else if (edgesCount == 4)   // 腰孔，由两条边，两个圆弧组成
                    {
                        foreach (SketchSegment sketchSegment in countourSegments)   // 遍历腰孔的每个Segment对象
                        {
                            sketchSegment.Select(false);
                            topAsemDoc.SketchConstraintsDel(0, "sgOFFSETEDGE");

                        }
                        // 旋转槽口
                        RotationSlotHole(countour);
                    }
                }
            }

            #endregion 映射孔的实体引用
            //mappingSketch
            // 选择映射的草图
            (mappingSketch as Entity).Select(false);
            // 开孔
            Feature featCut = featMgr.FeatureCut4(false, false, false, 1, 1, 1, 1, false, false, false, false, 1.74532925199433E-02, 1.74532925199433E-02, false, false, false, false, false, false, false, true, true, false, 0, 0, false, false);

            (topAsemDoc as AssemblyDoc).EditAssembly();// 退出编辑零件
        }


        private void RotationSlotHole(SketchContour countour)
        {

            object[] countourSegments = (object[])countour.GetSketchSegments();
            var edgesCount = countourSegments.Length;    // 草图轮廓包含的草图段数量
            List<Curve> slotHalfCircle = new List<Curve>();  // 槽口包含的两个半圆

            // 获得旋转点,  槽口两个半圆圆心的 中间点

            // 获得槽口的两个半圆
            foreach (SketchSegment sketchSegment in countourSegments)   // 遍历腰孔的每个Segment对象
            {
                sketchSegment.Select(true);
                Curve curve = sketchSegment.IGetCurve();
                if (curve.IsCircle())
                {
                    slotHalfCircle.Add(curve);
                }
                if (slotHalfCircle.Count == 2)
                {
                    break;
                }
            }


            Curve c1 = slotHalfCircle[0];
            Curve c2 = slotHalfCircle[1];

            double[] c1Info = (double[])c1.CircleParams;
            double[] c2Info = (double[])c2.CircleParams;

            double c1X = c1Info[0];
            double c1Y = c1Info[1];
            double c2X = c2Info[0];
            double c2Y = c2Info[1];

            // 获得两点中点
            double rotaionX = (c2X + c1X) / 2;
            double rotaionY = (c2Y + c1Y) / 2;

            countour.Select(false, -1);
            topAsemDoc.Extension.RotateOrCopy(false, 1, false, rotaionX, rotaionY, 0, 0, 0, 1, Math.PI / 2);

        }

        private void selectAllHoldInFace(Face2 face)
        {
            object[] loops = (object[])face.GetLoops();

            foreach (Loop2 loop in loops)       //面上面的环（Loop）对象
            {
                bool isLoopOuter = loop.IsOuter();

                // 如果是最外边包围框 跳过
                if (isLoopOuter)
                {
                    object[] vertices = (object[])loop.GetVertices();   //获得所有环的顶点
                    continue;
                }

                object[] edges = (object[])loop.GetEdges();

                // 此Loop只有一个Edge对象，极有可能是个圆环
                if (edges.Length == 1)
                {
                    Edge edge = (Edge)edges[0];
                    CurveParamData curveParama = edge.GetCurveParams3(); // 获取曲线类型
                    Curve curve = (Curve)edge.GetCurve();
                    if (curve.IsCircle()) // 如果是圆
                    {
                        loop.Select(null, true, null);
                        continue;
                    }
                }
                else if (edges.Length == 4) // 此Loop有四个Edge对象，可能是腰孔，也有可能是其他具有四条边的图形
                {
                    int arcCount = 0;
                    int lineCount = 0;
                    Curve[] circleCurves = new Curve[2];
                    Curve[] lineCurves = new Curve[2];
                    for (int i = 0; i < edges.Length; i++)
                    {
                        Edge edge = edges[i] as Edge;
                        Curve curve = (Curve)edge.GetCurve();
                        if (curve != null)
                        {
                            if (curve.IsCircle())
                            {
                                circleCurves[arcCount] = curve;
                                arcCount++;
                            }
                            else if (curve.IsLine())
                            {
                                lineCurves[lineCount] = curve;
                                lineCount++;
                            }
                            else
                            {
                            }
                        }
                    }
                    if (arcCount == lineCount && arcCount == 2) //槽口有两条线，两个半圆
                    {
                        double[] circleParadata0 = (double[])circleCurves[0].CircleParams;
                        double[] circleParadata1 = (double[])circleCurves[1].CircleParams;

                        double radius = Math.Round(circleParadata0[6] * 1000, 2);  // 槽口的半径1
                        double radius2 = Math.Round(circleParadata1[6] * 1000, 2);  // 槽口的半径2
                        if (radius != radius2)
                        {
                            Debug.Print("两圆两线，半径不相同，非槽口");
                            continue;
                        }
                        loop.Select(null, true, null);
                    }
                }
            }
        }

        public bool OnHelp()
        {
            return false;
        }

        public bool OnPreviousPage()
        {
            throw new NotImplementedException();
        }

        public bool OnNextPage()
        {
            throw new NotImplementedException();
        }

        public bool OnPreview()
        {
            throw new NotImplementedException();
        }

        public void OnWhatsNew()
        {
            throw new NotImplementedException();
        }

        public void OnUndo()
        {
            throw new NotImplementedException();
        }

        public void OnRedo()
        {
            throw new NotImplementedException();
        }

        public bool OnTabClicked(int Id)
        {
            throw new NotImplementedException();
        }

        public void OnGroupExpand(int Id, bool Expanded)
        {
            throw new NotImplementedException();
        }

        public void OnGroupCheck(int Id, bool Checked)
        {
            throw new NotImplementedException();
        }

        public void OnCheckboxCheck(int Id, bool Checked)
        {
            if (Id == UserPMPForOpenHole.checkBoxSlotRotaionId)
            {
                if (Checked == true)
                {
                    RotaionSlotHole = true;
                }
                else if (Checked == false)
                {
                    RotaionSlotHole = false;

                }
            }

        }

        public void OnOptionCheck(int Id)
        {
            throw new NotImplementedException();
        }

        public void OnButtonPress(int Id)
        {
            throw new NotImplementedException();
        }

        public void OnTextboxChanged(int Id, string Text)
        {
            throw new NotImplementedException();
        }

        public void OnNumberboxChanged(int Id, double Value)
        {
            throw new NotImplementedException();
        }

        public void OnComboboxEditChanged(int Id, string Text)
        {
            throw new NotImplementedException();
        }

        public void OnComboboxSelectionChanged(int Id, int Item)
        {
            throw new NotImplementedException();
        }

        public void OnListboxSelectionChanged(int Id, int Item)
        {
        }

        public void OnSelectionboxFocusChanged(int Id)
        {
        }

        public void OnSelectionboxListChanged(int Id, int Count)
        {
        }

        public void OnSelectionboxCalloutCreated(int Id)
        {
        }

        public void OnSelectionboxCalloutDestroyed(int Id)
        {
            // 
            var x = Id;
        }

        public bool OnSubmitSelection(int Id, object Selection, int SelType, ref string ItemText)
        {
            // 孔基准面ID
            if (Id == UserPMPForOpenHole.seletionFaceBaseId)
            {
                //ppage.seletionFaceTarget.SetSelectionFocus();
                return true;
            }
            else if (Id == UserPMPForOpenHole.seletionFaceTargetId)
            {
                return true;
            }
            return false;
        }

        public int OnActiveXControlCreated(int Id, bool Status)
        {
            throw new NotImplementedException();
        }

        public void OnSliderPositionChanged(int Id, double Value)
        {
            throw new NotImplementedException();
        }

        public void OnSliderTrackingCompleted(int Id, double Value)
        {
            throw new NotImplementedException();
        }

        public bool OnKeystroke(int Wparam, int Message, int Lparam, int Id)
        {
            throw new NotImplementedException();
        }

        public void OnPopupMenuItem(int Id)
        {
            throw new NotImplementedException();
        }

        public void OnPopupMenuItemUpdate(int Id, ref int retval)
        {
            throw new NotImplementedException();
        }

        public void OnGainedFocus(int Id)
        {
            throw new NotImplementedException();
        }

        public void OnLostFocus(int Id)
        {
            throw new NotImplementedException();
        }

        public int OnWindowFromHandleControlCreated(int Id, bool Status)
        {
            throw new NotImplementedException();
        }

        public void OnListboxRMBUp(int Id, int PosX, int PosY)
        {
            throw new NotImplementedException();
        }

        public void OnNumberBoxTrackingCompleted(int Id, double Value)
        {
            throw new NotImplementedException();
        }
    }
}